package service

import (
	"fmt"
	"io"
	"log"

	"com.zkh/agent/coap/global"
	"com.zkh/agent/coap/objs"
	"com.zkh/agent/coap/tcp"
	"com.zkh/agent/coap/utils"

	"github.com/plgd-dev/go-coap/v3/message"
	"github.com/plgd-dev/go-coap/v3/message/codes"
	"github.com/plgd-dev/go-coap/v3/message/pool"
)

func ForwardToDeviceCloud(c *tcp.Client, r *pool.Message) {
	path, _ := r.Options().Path()
	// 8-PSH 16-ack
	// r.ETag()
	log.Printf(" Got ForwardToDeviceCloud message: path=%q: from %v; code=%v; type=%v \n", path, c.Conn().RemoteAddr(), r.Code(), r.Type())
	if r.Body() == nil {
		if r.Code() == codes.CSM {
			// CSM
			log.Printf("CSM 处理！\n")
		}
		/*
			1）客户端开始请求CSM握手，可以通过判断消息，Seq=1，且Flags =  ACK, payload Len=0; 收到这帧数据，你就回客户端CSM握手信息
			2）服务端回给客户端的CSM握手信息，组的帧要求，
				A) Flags = PSH + ACK （值是0x18）
				B) Option是客户端附带过来的 tcp.options.timestamp（TSval和TSecr值）
				C）payload 7个字节，先写死默认交互MTU 1152字节： 50 e1 23 80 01 00 20
			3）后面客户端回给服务端的7个字节payload，50开头的帧，可以先忽略
		*/
		log.Printf("nil body 丢弃!")
		return
	}
	body, err := io.ReadAll(r.Body())
	if err != nil {
		log.Printf("ForwardToDeviceCloud 读取body错误！%v\n", err)
		return
	}
	log.Printf("options=: %v \n", r.Options())
	mapOpts := objs.OptionsToMap(r.Options())
	log.Printf("mapOpts:%+v", mapOpts)
	deviceId := mapOpts["DEV_ID"]
	reqId := mapOpts["REQ_ID"]
	tokenId := mapOpts["ACCESS_TOKEN_ID"]
	encryptMode, _ := utils.GetEncryptMode(deviceId)
	// 定义变量
	data := body
	if encryptMode == "plaintext" || path == "/.sys/psk" || encryptMode == "" {
	} else if encryptMode == "AES-128-CBC" {
		// 获取去掉HMAC后的加密报文
		msg := len(body) - 32
		encryptData := body[:msg]
		// 对加密报文进行解析
		data, err = utils.DecryptAESCBCData(deviceId, encryptData)
	} else {
		// 获取去掉HMAC后的加密报文
		msg := len(body) - 32
		encryptData := body[:msg]
		// 对加密报文进行解析
		data, err = utils.DecryptAESGCMData(deviceId, encryptData)
	}
	log.Printf("deviceId=%s,reqId=%s,tokenId=%s\n", deviceId, reqId, tokenId)
	// 非法连接直接断开
	if deviceId == "" || reqId == "" {
		log.Println("非法连接直接断开：缺少 deviceId 或 reqId ")
		c.Close()
		return
	}
	// 非法连接直接断开
	if tokenId == "" {
		if path == "/.sys/psk" || path == "/.sys/login" || path == "/.sys/activate" {
		} else {
			log.Println("非法连接直接断开：缺少 tokenId ")
			c.Close()
			return
		}
	}
	switch path {
	/*要加密故无法在此处处理
	case "/.sys/heartbeat":
		retJson := `{
			"timestamp": ` + fmt.Sprintf("%v", time.Now().UnixMilli()) + `
		}`
		c.Response(r.Token(), codes.Content, message.AppJSON, bytes.NewReader([]byte(retJson)), r.Options()...)
		return
	*/
	case "": // 没有path 就当作是下发的响应
		reqIdCacheKey := deviceId + "-" + reqId
		value, ok := reqIdCache.Get(reqIdCacheKey)
		if !ok { // 说明响应超时了丢弃
			log.Printf("丢弃过期的响应！reqIdCacheKey:%s,body:=%s\n", reqIdCacheKey, string(data))
			return
		}

		tmpChan := value.(chan objs.HttpCoapRet)
		retData := objs.HttpCoapRet{}
		retData.Option = mapOpts
		retData.Body = string(data)
		utils.ChanSafeWrite(tmpChan, retData)
		return

	}
	retStr := `{
		"errcode": 0,
		"devId": "xxx",
	}`

	resp, err := SendToCloudCmd(objs.HttpReq{Body: string(data), Url: path, Option: mapOpts, Method: r.Code().String()})
	if err != nil {
		log.Printf("ForwardToDeviceCloud 执行错误:%v\n", err)
		retStr = `{"errcode":100}`
	}
	log.Printf("ForwardToDeviceCloud 执行成功:%+v\n", resp)
	opts := objs.MapToOptions(resp.Data.Option)

	switch resp.Code {
	case 200:
		retStr = resp.Data.Body
		if path == "/.sys/login" {
			log.Printf("设备登录成功，deviceId=%s,oldId=%s\n", deviceId, c.GetId())
			oldId := c.GetId()
			c.SetId(deviceId)
			global.CoapServer.Manager.Updata(oldId, c)
		}

	case 700:
		c.Response(deviceId, path, r.Token(), codes.Content, message.TextPlain, []byte(retStr), opts...)
		c.Close()
		return
	default:
		retStr = fmt.Sprintf(`{"errcode": %d,"msg":"%s"}`, resp.Code, resp.Msg)
	}

	c.Response(deviceId, path, r.Token(), codes.Content, message.TextPlain, []byte(retStr), opts...)
}
